#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#include "include_all.h"

struct test
{
	unsigned char tast[16];
};

static void *thread_broadcase_send(void *);
static int port_nums(unsigned short);

static struct watchdog_info *wtd = NULL;

int broadcase_init(struct watchdog_info *watchdog, int port)
{
	pthread_t tid = (pthread_t)0;

	const int opt = 1;
	int *sock = NULL;

	wtd = watchdog;

	sock = (int *)malloc(sizeof(int));

	*sock = socket(AF_INET, SOCK_DGRAM, 0);
	if(*sock < 0)
	{
		return RET_FAIL;
	}

	if(setsockopt(*sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0)
	{
		return RET_FAIL;
	}

	if(pthread_create(&tid, NULL, thread_broadcase_send, sock) == 0)
	{
		return RET_OK;
	}

	return RET_FAIL;
}

static int port_nums(unsigned short num)
{
	if(num >= 0 && num < 10)
	{
		return 1;
	}
	else if(num >= 10 && num < 100)
	{
		return 2;
	}
	else if(num >= 100 && num < 1000)
	{
		return 3;
	}
	else if(num >= 1000 && num < 10000)
	{
		return 4;
	}
	else
	{
		return 5;
	}
}

static void *thread_broadcase_send(void *arg)
{
	int i = 0;
	int *sock = (int *)arg;
	const int port_bit_size = port_nums((unsigned short)TCP_PORT);
	char sendbuf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	unsigned char tcp_port_buf[port_bit_size];

	struct sockaddr_in broadcast_addr;

	memset(tcp_port_buf, 0, sizeof(tcp_port_buf));
	memset(&broadcast_addr, 0, sizeof(struct sockaddr_in));
	broadcast_addr.sin_family = AF_INET;
	broadcast_addr.sin_port = htons(BROADCASE_PORT);
	broadcast_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);

	snprintf(sendbuf, (sizeof(sendbuf) / sizeof(sendbuf[0])), "%d", TCP_PORT);
	for(i = 0; i < port_bit_size; i++)
	{
		tcp_port_buf[i] = (unsigned char)sendbuf[i];
	}

#if DEBUG
	printf("\n#########################################################\nbroadcast start!\n\nbroadcast address:\t%s\nbroadcast port:\t\t%d\ntcp port:\t\t%d\n#########################################################\n\n", inet_ntoa(broadcast_addr.sin_addr), BROADCASE_PORT, TCP_PORT);
#endif

	wtd->run_reg(RT_UDP);
	while(wtd->run_get(0) > 0)
	{
		if(sendto(*sock, tcp_port_buf, sizeof(tcp_port_buf), 0, (struct sockaddr *)&broadcast_addr, sizeof(struct sockaddr_in)) < 0)
		{
			wtd->report_reg(__func__, "Send broadcase failed", NULL);
		}
		sleep(BROADCASE_INTERVAL);
	}
	close(*sock);
	free(sock);

#if DEBUG
	printf("%s: send stop, I will exit!\n", __func__);
#endif

	wtd->run_unreg(RT_UDP);
	return NULL;
}
